package com.blb.community.Config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.blb.community.pojo.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder()  {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    private UserDetailsService userDetailsService;


    @Autowired
    private DataSource dataSource;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.inMemoryAuthentication().withUser("admin")
//                .password(bCryptPasswordEncoder.encode("123"))
//                .roles("admin")
//                .authorities("adminAdd")
//                .and()
//                .withUser("user").password(bCryptPasswordEncoder.encode("12345"))
//                .roles("user");
        auth.userDetailsService(userDetailsService);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.authorizeRequests().antMatchers(
//                "/**/*.css","/**/*.js","/**/*.jpg","/login","/login.html","/logout"
//        ).permitAll()
//                .antMatchers("/admin.html").hasRole("admin")
//                .antMatchers("/admin-add.html").hasAuthority("仓库管理")
//                .antMatchers("/user.html").hasAnyRole("admin","user")
//                .anyRequest().authenticated()
//                .and().formLogin().loginPage("/login")
//                .successForwardUrl("/index")
//                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/login")
//                .and()
//                .rememberMe().tokenRepository(persistentTokenRepository).rememberMeParameter("rememberMe").tokenValiditySeconds(120);
        http.authorizeRequests().antMatchers(
                "/**/*.css", "/**/*.js", "/**/*.jpg", "/login","/login.html", "/logout"
        ).permitAll()
                .anyRequest().authenticated()
                .and().formLogin().successHandler(new successHandlerConfig())
                .failureHandler(((request, response, e) -> {
                        ResponseResult.write(ResponseResult.error( 401L,"用户名不存在或密码错误"), response);
                }))
                .and().exceptionHandling().authenticationEntryPoint(((request, response, e) -> {
            ResponseResult.write(ResponseResult.error(403L,"无权限访问" ), response);
        }))
                .and().logout().logoutSuccessHandler(((request, response, e) -> {
            ResponseResult.write(ResponseResult.ok("注销成功"), response);
        }))
                .clearAuthentication(true)
                .and().csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .addFilter(new TokenAuthenticationFilter(authenticationManager()));
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
//        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    /**
     * 跨域配置对象
     *
     * @return
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        //配置允许访问的服务器域名
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().mvcMatchers("/upload","/yzm","/zy/registerOwner","/complaintSuggest/uploadImage","/upload/repair");
    }
}
